//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package impl

import (
	"context"

	"atomgit.com/openlinksaas-org/proxy/redis_pkg/gen_code"
	"github.com/go-redis/redis/v8"
	"github.com/google/uuid"
)

type ConnectionApiImpl struct{}

func (s *ConnectionApiImpl) OpenPost(ctx context.Context, req gen_code.OpenPostRequest) (gen_code.ImplResponse, error) {
	if req.Token != token {
		return gen_code.ImplResponse{
			Code: 500,
			Body: gen_code.ErrInfo{
				ErrMsg: "wrong token",
			},
		}, nil
	}
	if len(req.Hosts) < 1 {
		return gen_code.ImplResponse{
			Code: 500,
			Body: gen_code.ErrInfo{
				ErrMsg: "need hosts param",
			},
		}, nil
	}
	id := uuid.NewString()
	if req.Cluster {
		c := redis.NewClusterClient(&redis.ClusterOptions{
			Addrs:    req.Hosts,
			Username: req.Username,
			Password: req.Password,
		})
		_, err := c.Ping(ctx).Result()
		if err != nil {
			c.Close()
			return gen_code.ImplResponse{
				Code: 500,
				Body: gen_code.ErrInfo{
					ErrMsg: err.Error(),
				},
			}, nil
		}
		clientMap.Store(id, &ClientInfo{
			Name:    req.Name,
			Db:      int(req.Db),
			Cluster: true,
			client:  c,
		})
	} else {
		c := redis.NewClient(&redis.Options{
			Addr:     req.Hosts[0],
			Username: req.Username,
			Password: req.Password,
			DB:       int(req.Db),
		})
		_, err := c.Ping(ctx).Result()
		if err != nil {
			c.Close()
			return gen_code.ImplResponse{
				Code: 500,
				Body: gen_code.ErrInfo{
					ErrMsg: err.Error(),
				},
			}, nil
		}
		clientMap.Store(id, &ClientInfo{
			Name:    req.Name,
			Db:      int(req.Db),
			Cluster: false,
			client:  c,
		})

	}
	return gen_code.ImplResponse{
		Code: 200,
		Body: id,
	}, nil
}

func (s *ConnectionApiImpl) ClosePost(ctx context.Context, req gen_code.ClosePostRequest) (gen_code.ImplResponse, error) {
	if req.Token != token {
		return gen_code.ImplResponse{
			Code: 500,
			Body: gen_code.ErrInfo{
				ErrMsg: "wrong token",
			},
		}, nil
	}
	infoItem, ok := clientMap.Load(req.Id)
	if !ok {
		return gen_code.ImplResponse{
			Code: 200,
			Body: req.Id,
		}, nil
	}
	info := infoItem.(*ClientInfo)
	if info.Cluster {
		c := info.client.(*redis.ClusterClient)
		c.Close()
	} else {
		c := info.client.(*redis.Client)
		c.Close()
	}
	clientMap.Delete(req.Id)
	return gen_code.ImplResponse{
		Code: 200,
		Body: req.Id,
	}, nil

	return gen_code.ImplResponse{
		Code: 200,
		Body: req.Id,
	}, nil
}

func (s *ConnectionApiImpl) ListPost(ctx context.Context, req gen_code.ListPostRequest) (gen_code.ImplResponse, error) {
	if req.Token != token {
		return gen_code.ImplResponse{
			Code: 500,
			Body: gen_code.ErrInfo{
				ErrMsg: "wrong token",
			},
		}, nil
	}
	retList := []gen_code.ListPost200ResponseInner{}
	clientMap.Range(func(key, value any) bool {
		info := value.(*ClientInfo)
		retList = append(retList, gen_code.ListPost200ResponseInner{
			Id:   key.(string),
			Name: info.Name,
			Db:   int32(info.Db),
		})
		return true
	})
	return gen_code.ImplResponse{
		Code: 200,
		Body: retList,
	}, nil
}
